package dbTest

import kotlinx.coroutines.*
import java.sql.*
import java.util.concurrent.atomic.AtomicInteger
import kotlin.random.Random
import kotlin.time.Duration.Companion.seconds

/**
 * 数据库基准测试抽象基类
 */
abstract class DatabaseBenchmark(
    val dbName: String,
    val jdbcUrl: String,
    val username: String,
    val password: String
) {
    private val totalRequests = AtomicInteger(0)
    private val successfulRequests = AtomicInteger(0)
    private val failedRequests = AtomicInteger(0)
    
    // 测试持续时间（秒）
    var testDuration = 30
    
    // 并发用户数
    var concurrentUsers = 1000

    /**
     * 获取数据库连接
     */
    fun getConnection(): Connection {
        return DriverManager.getConnection(jdbcUrl, username, password)
    }

    /**
     * 创建测试表
     */
    abstract fun createTable()

    /**
     * 插入数据
     */
    abstract fun insertData()

    /**
     * 查询数据
     */
    abstract fun selectData()

    /**
     * 更新数据
     */
    abstract fun updateData()

    /**
     * 删除数据
     */
    abstract fun deleteData()

    /**
     * 执行单次CRUD操作
     */
    private fun performCRUD() {
        totalRequests.incrementAndGet()
        try {
            insertData()
//            selectData()
//            updateData()
//            deleteData()
            successfulRequests.incrementAndGet()
        } catch (e: Exception) {
            failedRequests.incrementAndGet()
            println("Error in $dbName operation: ${e.message}")
        }
    }

    /**
     * 单个用户执行测试
     */
    private suspend fun userTask() {
        while (true) {
//            val startTime = System.currentTimeMillis()
            performCRUD()
//            val endTime = System.currentTimeMillis()
//            // 1次 10ms 1s 100次，10 个线程并行 1000次，30s 就是 30000
//            if(endTime - startTime > 100) {
//                println("performCRUD 耗时 ${endTime - startTime} ms")
//            }
//            delay(10) // 简短延迟以控制请求频率
        }
    }

    /**
     * 运行基准测试
     */
    suspend fun runBenchmark(): BenchmarkResult {
        println("Starting $dbName benchmark...")
        
        // 创建表
        try {
            createTable()
            println("$dbName table created successfully")
        } catch (e: Exception) {
            println("Failed to create $dbName table: ${e.message}")
        }

        // 重置计数器
        totalRequests.set(0)
        successfulRequests.set(0)
        failedRequests.set(0)

        // 启动并发用户
        val startTime = System.currentTimeMillis()

        val scope = CoroutineScope(Dispatchers.Default)
        val jobs = mutableListOf<Job>()

        repeat(concurrentUsers) {
            val job = scope.launch {
                userTask()
            }
            jobs.add(job)
        }

        // 运行指定时间
        delay(testDuration.seconds)
        jobs.forEach { it.cancel() }
        
        val endTime = System.currentTimeMillis()
        val durationSeconds = (endTime - startTime) / 1000.0
        val qps = successfulRequests.get() / durationSeconds

        return BenchmarkResult(
            dbName = dbName,
            totalRequests = totalRequests.get(),
            successfulRequests = successfulRequests.get(),
            failedRequests = failedRequests.get(),
            qps = qps,
            durationSeconds = durationSeconds
        )
    }

    /**
     * 基准测试结果数据类
     */
    data class BenchmarkResult(
        val dbName: String,
        val totalRequests: Int,
        val successfulRequests: Int,
        val failedRequests: Int,
        val qps: Double,
        val durationSeconds: Double
    ) {
        val successRate: Double = if (totalRequests > 0) successfulRequests.toDouble() / totalRequests * 100 else 0.0
        val failureRate: Double = if (totalRequests > 0) failedRequests.toDouble() / totalRequests * 100 else 0.0

        fun printResult() {
            println("\n========== $dbName Benchmark Result ==========")
            println("Total Requests: $totalRequests")
            println("Successful Requests: $successfulRequests")
            println("Failed Requests: $failedRequests")
            println("Success Rate: ${String.format("%.2f", successRate)}%")
            println("Failure Rate: ${String.format("%.2f", failureRate)}%")
            println("QPS (Queries Per Second): ${String.format("%.2f", qps)}")
            println("Test Duration: ${String.format("%.2f", durationSeconds)} seconds")
            println("=============================================\n")
        }
    }
}